/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.deployment.dao;

import br.com.deployment.daogenerico.DaoGenerico;
import br.com.deployment.entidade.acesso.Usuario;
import br.com.deployment.entidade.fermojupi.AtoItem;
import br.com.deployment.entidade.selo.DetalheEntradaSelo;
import br.com.deployment.entidade.selo.Distribuicao;
import br.com.deployment.entidade.selo.Selo;
import br.com.deployment.entidade.selo.TipoSelo;
import br.com.deployment.enums.Relatorio;
import br.com.deployment.interfaces.SeloDaoIn;
import br.com.deployment.servico.CartorioServico;
import br.com.deployment.utilitario.GeraRelatorio;
import br.com.deployment.utilitario.Msg;
import java.text.SimpleDateFormat;
import java.util.*;
import javax.ejb.EJB;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.persistence.NoResultException;
import javax.persistence.NonUniqueResultException;
import javax.persistence.Query;

/**
 *
 * @author elyjr
 */
@Stateless
@LocalBean
public class SeloDao extends DaoGenerico<Selo> implements SeloDaoIn{

    @EJB
    CartorioServico cartorioServico;
        
    public SeloDao() {
        super(Selo.class);
    }

    public void editSelos(List<Selo> selos) {
        for (Selo selo : selos) {
            getEm().merge(selo);
        }
    }

    public void cancelar(List<Selo> s) {
        StringBuffer str = new StringBuffer();
        try {
            System.err.println("Lista: " + s);
            for (Selo cancel : s) {
                cancel = findSelo(cancel.getNumero(), cancel.getSerie(), cancel.getTipoSelo());
                cancel.setProtocolado(false);
                cancel.setAtivo(false);
                getEm().merge(cancel);
                str.append(cancel.getNumero() + ",");
                System.err.println(cancel);
            }
            Msg.messagemInfo("Selo Nº " + str.toString() + " cancelado !");
        } catch (NoResultException e) {
            Msg.messagemError("Erro ao cancelar selos");
        }



    }

    public Selo findNumeracao(int numeracao, int serie) {
        Selo selo = new Selo();
        String sql = "select s from Selo s";
        Query query = getEm().createQuery(" where s.numeracao = :num and s.serie = serie");
        query.setParameter(":num", numeracao);
        query.setParameter(":serie", serie);
        selo = (Selo) query.getSingleResult();
        return selo;
    }

    @Override
    public List<Selo> findAll() {
        List<Selo> lista = new ArrayList<Selo>();
        String sql = "select s from Selo s ";
        Query query = getEm().createQuery(sql);
        lista = query.getResultList();
        return lista;
    }

     
    public boolean exist(Selo se, boolean msg) {
        try {
                        
            findSelo(se.getNumero(), se.getSerie(), se.getTipoSelo());
        } catch (NoResultException ne) {
            if (msg) {
                Msg.messagemError("Selo inexistente ");
            }
            return false;
        } catch (NonUniqueResultException nure) {
            if (msg) {
                Msg.messagemError("Erro interno, foram encontrados selos duplicados ");
            }
            return false;
        }

        return true;
    }

    
    public Selo findSelo(int numeracao, String serie, TipoSelo tipoSelo) {
        Selo selo = new Selo();
        String sql = "select s from Selo s ";

        if (tipoSelo != null) {
            sql += " JOIN s.tipoSelo ts ";
        }
        sql += " where s.numero = :num and s.serie = :serie and s.ativo = true";

        if (tipoSelo != null) {
            sql += " and ts.id = :id";
        }

        Query query = getEm().createQuery(sql);

        query.setParameter("num", numeracao);
        query.setParameter("serie", serie);
        query.setParameter("id", tipoSelo.getId());
        System.err.println(query.getResultList());

        selo = (Selo) query.getSingleResult();
        return selo;
    }

    
    public Long qtdSelo(Usuario u, TipoSelo tSelo) {
        Long qtd = 0L;
        String sql = "select count(s) from Selo s JOIN s.tipoSelo ts "
                + " JOIN s.detalheEntradaSelo ds "
                + " JOIN ds.entradaSelo es JOIN es.usuario u where"
                + " u.nome = :nome and"
                + " ts.id = :id and s.ativo = true and s.distribuido = true "
                + " and s.status = true";
        Query query = getEm().createQuery(sql);
        query.setParameter("nome", u.getNome());
        query.setParameter("id", tSelo.getId());
        qtd = (Long) query.getSingleResult();
        System.err.println(sql);
        return qtd;
    }

    /**
     * Busca a quantidade de selos do tipo, passado por parâmetro, que estejam
     * ativo distribuido e status true
     *
     * @param tSelo
     * @return e
     */
    public Long qtdSeloAll(TipoSelo tSelo) {
        Long qtd = 0L;
        String sql = "select count(s) from Selo s JOIN s.tipoSelo ts where"
                + " ts.id = :id"
                + " and s.ativo = true"
                + " and s.distribuido = false "
                + " and s.protocolado = false";
        Query query = getEm().createQuery(sql);
        query.setParameter("id", tSelo.getId());
        qtd = (Long) query.getSingleResult();
        System.err.println("qtd ::: " + qtd);
        return qtd;
    }

    public Long qtdSeloDistribuido(TipoSelo tSelo) {
        Long qtd = 0L;
        String sql = "select count(s) from Selo s JOIN s.tipoSelo ts "
                + " ts.id = :id and s.ativo = true and s.distribuido = true "
                + " and s.protocolado = false";
        Query query = getEm().createQuery(sql);
        query.setParameter("id", tSelo.getId());
        qtd = (Long) query.getSingleResult();
        return qtd;
    }

    public Long qtdSeloSairam(TipoSelo tSelo) {
        Long qtd = 0L;
        String sql = "select count(s) from Selo s JOIN s.tipoSelo ts where "
                + " ts.id = :id and s.ativo = true and s.distribuido = true "
                + " and s.protocolado = true";

        Query query = getEm().createQuery(sql);
        query.setParameter("id", tSelo.getId());
        qtd = (Long) query.getSingleResult();
        return qtd;
    }

    public Long qtdSeloSairamMes( Date dataIni, Date dataFim) {

        Long qtd = 0L;
        String sql = "select count(s) from Selo s  where "
                + " s.ativo = true"
                + " and s.distribuido = true "
                + " and s.protocolado = true"
                + " and s.dataProtocolado BETWEEN :dataIni AND :dataFim";
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Query query = getEm().createQuery(sql);
            query.setParameter("dataIni", dataIni);
            query.setParameter("dataFim", dataFim);
            System.err.println(sdf.format(dataIni) + " e " + sdf.format(dataFim) + " SAIDA ----:  " + query.getResultList());
        

        
        qtd = (Long) query.getSingleResult();
        return qtd;

    }

    public Long qtdSeloCancelado(TipoSelo tSelo) {
        Long qtd = 0L;
        String sql = "select count(s) from Selo s JOIN s.tipoSelo ts where "
                + " ts.id = :id and s.ativo = false "
                + " and s.protocolado = false";
        Query query = getEm().createQuery(sql);
        query.setParameter("id", tSelo.getId());
        qtd = (Long) query.getSingleResult();
        return qtd;
    }
    

    public boolean existSeloEditar(int numeracao, String serie, TipoSelo tipoSelo, int detalhe) {
        Selo selo = new Selo();
        String sql = "select s from Selo s JOIN s.detalheEntradaSelo de";

        if (tipoSelo != null) {
            sql += " JOIN s.tipoSelo ts ";
        }
        sql += " where s.numero = :num and s.serie = :serie and s.ativo = true";

        if (tipoSelo != null) {
            sql += " and ts.id = :id";
        }

        sql += " and de.id != :idDetalhe";


        Query query = getEm().createQuery(sql);

        query.setParameter("num", numeracao);
        query.setParameter("serie", serie);
        query.setParameter("id", tipoSelo.getId());
        query.setParameter("idDetalhe", detalhe);

        try {
            selo = (Selo) query.getSingleResult();
            return true;
        } catch (NoResultException e) {
            return false;
        }
    }

    public void removeSelos(DetalheEntradaSelo es) {
        String sql = "delete from Selo s where s.detalheEntradaSelo.id = :id";
        Query q = getEm().createQuery(sql);
        q.setParameter("id", es.getId());
        q.executeUpdate();
    }

    public List<Selo> selosByUsuarioByAto(AtoItem atoItem, Usuario usr, List<Selo> notSelos) {
        System.err.println("Tam " + notSelos.size());
        List<Selo> selos = new ArrayList<Selo>();
        List<Selo> selosRem = new ArrayList<Selo>();
        int get = 0;
        if (atoItem != null) {
            if (usr != null) {
                 String sql = "";
                 Query q;
              if( atoItem.getTipoSelo() != null){
                sql += "select s from Distribuicao d JOIN d.listSelo s JOIN s.tipoSelo ts "
                        + " JOIN d.recebedor u where"
                        + " u.id = :usr and"
                        + " ts.id = :id and"
                        + " s.ativo = true and s.distribuido = true "
                        + " and s.protocolado = false  "
                        + " ";

                q = getEm().createQuery(sql).setMaxResults(notSelos.size() + 1);

                q.setParameter("id", atoItem.getTipoSelo().getId());
                q.setParameter("usr", usr.getId());

                try {
                    List<Selo> s = q.getResultList();


                    for (Selo selo : s) {
                        if (notSelos.contains(selo)) {
                            selosRem.add(selo);
                        } else {
                            selos.add(selo);
                            break;
                        }
                    }

                    notSelos.addAll(selos);
                    selosRem.clear();

                } catch (NoResultException nr) {
                    Msg.messagemInfo("Usuário não possui selos para o Item");
                }
              }
                //GRATUIDADE
                try {

                    sql = "select s from Distribuicao d JOIN d.listSelo s JOIN s.tipoSelo ts "
                            + " JOIN d.recebedor u where ts.gratuidade = true"
                            + " and s.distribuido = true"
                            + " and s.ativo = true"
                            + " and s.protocolado = false and u.id = :usr";

                    q = getEm().createQuery(sql).setMaxResults(notSelos.size() + 1);
                    q.setParameter("usr", usr.getId());

                    List<Selo> listGrat = q.getResultList();

                    get = 0;

                    for (Selo selo : listGrat) {
                        if (!notSelos.contains(selo)) {
                            selos.add(selo);
                            break;
                        }
                    }
                    System.err.println("2 - " + selos);
                    notSelos.addAll(selos);

                } catch (NoResultException nr) {
                    System.err.println("Usr não possui selos de gratuidade");
                }

                //ARQUIVAMENTO
                try {
                    sql = "select s from Distribuicao d JOIN d.listSelo s JOIN s.tipoSelo ts "
                            + " JOIN d.recebedor u where"
                            + " ts.arquivamento = true"
                            + " and s.distribuido = true"
                            + " and s.ativo = true"
                            + " and s.protocolado = false and u.id = :usr";

                    q = getEm().createQuery(sql).setMaxResults(notSelos.size() + 1);
                    q.setParameter("usr", usr.getId());

                    List<Selo> listArq = q.getResultList();

                    get = 0;

                    for (Selo selo : listArq) {
                        if (!notSelos.contains(selo)) {
                            selos.add(selo);
                            break;
                        }
                    }
                    System.err.println("3 - " + selos);

                } catch (NoResultException nr) {
                    System.err.println("Usr não possui selos de arquivamento");
                }

            } else {
                return null;
            }
        } else {
            Msg.messagemError("Ato não possui Selo vinculado");
            throw new NoResultException();
        }
        return selos;
    }

    public Selo findSeloUsr(int numeracao, String serie, TipoSelo tipoSelo, Usuario usr) {
        Selo selo = new Selo();
        String sql = "select s from Distribuicao d JOIN d.listSelo s "
                + " JOIN s.tipoSelo ts "
                + " JOIN d.recebedor u where "
                + " u.id = :usr and";

        sql += "  s.numero = :num and s.serie = :serie and s.ativo = true";

        sql += " and ts.id = :id and s.distribuido = true and s.ativo = true and s.protocolado = false";

        Query query = getEm().createQuery(sql);

        query.setParameter("num", numeracao);
        query.setParameter("serie", serie);
        query.setParameter("id", tipoSelo.getId());
        query.setParameter("usr", usr.getId());
        System.err.println(query.getResultList());
        try {
            selo = (Selo) query.getSingleResult();
        } catch (Exception e) {
            Msg.messagemError(" Selo indisponível !");
            throw new NoResultException();
        }
        return selo;
    }

    public void seloNaoUsado(Selo s, TipoSelo ts, Date dataIni,
            Date dataFim, Distribuicao d, Integer numIni, Integer numFim) {

        String sql = "select s from Selo s";

        if(ts != null){
            sql += " JOIN s.tipoSelo ts ";
        }
        
        if (dataIni != null && dataFim != null) {
            sql += " JOIN s.detalheEntradaSelo des"
                    + " JOIN des.entradaSelo es";
        }
        if (d.getRecebedor() != null) {
            sql += " , Distribuicao d JOIN d.recebedor rc JOIN d.listSelo ls";
        }
       sql += " where s.ativo = true"
             + " and s.protocolado = false";
       
       if(s.getSerie() != null){
           sql +=" and s.serie like :serie";
       }
       if(numFim != null){
           sql +=" and s.numero  BETWEEN :numIni AND :numFim";
       }
        
        if(ts != null){
            sql += " and ts.id = :id";
        }
        
        if (dataIni != null && dataFim != null) {
            sql += " and des.dataEntrada BETWEEN :dataIni AND :dataFim";
        }
        if (d.getRecebedor() != null) {
            sql += " and rc.id = :recebedor and ls.id = s.id";
        }
        sql += " ORDER BY s.id ASC";

        Query query = getEm().createQuery(sql);
         if(ts != null){
            query.setParameter("id", ts.getId());
         }
        if (dataIni != null && dataFim != null) {
            
            query.setParameter("dataIni", dataIni);
            query.setParameter("dataFim", dataFim);
        }
         if(s.getSerie() != null){
              query.setParameter("serie", s.getSerie());
         }
        if(numFim != null){
            query.setParameter("numIni", numIni == null ? 1 : numIni);
            query.setParameter("numFim", numFim);
        
        }
        if (d.getRecebedor() != null) {
            query.setParameter("recebedor", d.getRecebedor().getId());
        }
        
        relatorioSeloProtocolo((List<Selo>) query.getResultList());
        
    }
    
    public void relatorioSeloProtocolo( List<Selo> s2) {
        System.err.println("RELATORIO SELO PROTOCOLO");
        
        GeraRelatorio geraRelatorio = new GeraRelatorio();

        HashMap<String, Object> parametros;
        parametros = new HashMap<String, Object>();
        parametros = cartorioServico.getCartorioRelatorio(parametros);
       
        
        geraRelatorio.relatorio(parametros, s2 , Relatorio.RELATORIO_SELO_NAO_USADO);
    }
}
